About this simulation

From previous analysis (“powerdown_unbalanced”), it appears that ComBat-seq works when there is variance batch effect AND when there is some level of confounding between batch and condition (i.e. in unbalanced study design). We dig deeper in these two factors.

Simulation setup

Note that the fixed parameters are consistent with (i.e. within the range of) my observations from real datasets (See explore_real_data for details).

Two factors under examination are dispersion fold change and level of confounding. Confounding level is measured by how many percentage of samples in batch 1 is control samples. 2 batches have the same size, but in batch 2, the number of controls and cases are reversed compared to batch 1. Grids for the two factors:

Results

TPR vs FPR

Line plots

Facet by confounding levels

Facet by dispersion levels

Scatter plots

TPR (sensitivity) vs FDR (1-precision)

Line plots

Facet by confounding levels

Facet by dispersion levels

Scatter plots

Similar plot (sensitivity vs 1-FDR) as Figure 6 in DESeq2 paper.

Thoughts & future work

LS0tCnRpdGxlOiAiQXBwbGljYXRpb24gb2YgQ29tQmF0LXNlcSBvbiBzaW11bGF0ZWQgZGF0YXNldHMiCnN1YnRpdGxlOiAiTGV2ZWxzIG9mIGRpc3BlcnNpb24gZGlmZmVyZW5jZXMgYW5kIGNvbmZvdW5kaW5nIgphdXRob3I6IFl1cWluZyBaaGFuZwpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgdGhlbWU6IHVuaXRlZAogICAgdG9jOiB5ZXMKLS0tCgojIyBBYm91dCB0aGlzIHNpbXVsYXRpb24KCkZyb20gcHJldmlvdXMgYW5hbHlzaXMgKCoicG93ZXJkb3duX3VuYmFsYW5jZWQiKiksIGl0IGFwcGVhcnMgdGhhdCBDb21CYXQtc2VxIHdvcmtzIHdoZW4gdGhlcmUgaXMgdmFyaWFuY2UgYmF0Y2ggZWZmZWN0ICoqQU5EKiogd2hlbiB0aGVyZSBpcyBzb21lIGxldmVsIG9mIGNvbmZvdW5kaW5nIGJldHdlZW4gYmF0Y2ggYW5kIGNvbmRpdGlvbiAoaS5lLiBpbiB1bmJhbGFuY2VkIHN0dWR5IGRlc2lnbikuIFdlIGRpZyBkZWVwZXIgaW4gdGhlc2UgdHdvIGZhY3RvcnMuCgoKIyMgU2ltdWxhdGlvbiBzZXR1cAoKKiBNZWFuIGZvbGQgY2hhbmdlczogQmlvbG9naWNhbCAtIDIsIEJhdGNoIC0gMS41IAoqIERpc3BlcnNpb246IEJhdGNoIDEgLSAwLjE1LCBCYXRjaCAyIC0gMC4xNSoqKmRpc3BlcnNpb24gZm9sZCBsZXZlbCoqCiogU3R1ZHkgZGVzaWduOiAqKkRpZmZlcmVudCBsZXZlbHMgb2YgY29uZm91bmRpbmcqKgoqIFJlYWRzIHBlciBnZW5lOiBNZWRpYW4gMTIwIChjb3ZlcmFnZSA1KQoqIFRvdGFsIG51bWJlciBvZiBzYW1wbGVzOiAyMCAoKndlIGxvb2sgYXQgTj02MCBsYXRlciBpbiBjb21wYXJpc29uIHRvIHNlZSBpZiBwYXR0ZXJucyBob2xkKikKCk5vdGUgdGhhdCB0aGUgZml4ZWQgcGFyYW1ldGVycyBhcmUgY29uc2lzdGVudCB3aXRoIChpLmUuIHdpdGhpbiB0aGUgcmFuZ2Ugb2YpIG15IG9ic2VydmF0aW9ucyBmcm9tIHJlYWwgZGF0YXNldHMgKFNlZSBleHBsb3JlX3JlYWxfZGF0YSBmb3IgZGV0YWlscykuIAoKVHdvIGZhY3RvcnMgdW5kZXIgZXhhbWluYXRpb24gYXJlIGRpc3BlcnNpb24gZm9sZCBjaGFuZ2UgYW5kIGxldmVsIG9mIGNvbmZvdW5kaW5nLiBDb25mb3VuZGluZyBsZXZlbCBpcyBtZWFzdXJlZCBieSAqKmhvdyBtYW55IHBlcmNlbnRhZ2Ugb2Ygc2FtcGxlcyBpbiBiYXRjaCAxIGlzIGNvbnRyb2wgc2FtcGxlcyoqLiAyIGJhdGNoZXMgaGF2ZSB0aGUgc2FtZSBzaXplLCBidXQgaW4gYmF0Y2ggMiwgdGhlIG51bWJlciBvZiBjb250cm9scyBhbmQgY2FzZXMgYXJlIHJldmVyc2VkIGNvbXBhcmVkIHRvIGJhdGNoIDEuIEdyaWRzIGZvciB0aGUgdHdvIGZhY3RvcnM6CgoqIERpc3BlcnNpb24gbGV2ZWw6IDEgKG5vIGRpc3BlcnNpb24gZGlmZmVyZW5jZSksIDIsIDMsIDQsIDUKKiBDb25mb3VuZGluZzogMC41IChubyBjb25mb3VuZGluZyksIDAuNCwgMC4zLCAwLjIKCmBgYHtyLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30Kcm0obGlzdD1scygpKQpzYXBwbHkoYygiZ2dwbG90MiIsICJncmlkRXh0cmEiLCAicmVzaGFwZTIiLCAiZ2dwdWJyIiksIHJlcXVpcmUsIGNoYXJhY3Rlci5vbmx5PVRSVUUpCnJlc3VsdHNfZGlyIDwtICJ+L0dvb2dsZSBEcml2ZS9Db21CYXRfc2VxL0RFX2Rpc3BfY29uZm91bmRpbmdfYmFzZSIKI3Jlc3VsdHNfZGlyIDwtICJ+L3l1cWluZ3ovQ29tQmF0X3NlcS9ERV9kaXNwX2NvbmZvdW5kaW5nX2Jhc2UiCk5fc2FtcGxlcyA8LSA2MAoKZGlzcF9sZXZlbF92ZWMgPC0gMTo1CmNvbmZvdW5kaW5nX2xldmVsX3ZlYyA8LSBzZXEoZnJvbT0wLjUsdG89MC4yLGJ5PS0wLjEpCnNlbF9tZXRob2RfbGlzdCA8LSBsaXN0KGVkZ2VSPWMoIkJhc2VJbmRpLmVkZ2VSIiwgIyJCYXNlUXVhbnQuZWRnZVIiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQmF0Y2guZWRnZVIiLCAiT25lU3RlcC5lZGdlUiIsICJDb21CYXQubG0iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUlVWc2VxLmVkZ2VSIiwgIlNWQXNlcS5lZGdlUiIsICJDb21CYXRzZXEuZWRnZVIiKSwKICAgICAgICAgICAgICAgICAgICAgICAgREVTZXEyPWMoIkJhc2VJbmRpLkRFU2VxMiIsICMiQmFzZVF1YW50LkRFU2VxMiIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQmF0Y2guREVTZXEyIiwgIk9uZVN0ZXAuREVTZXEyIiwgIkNvbUJhdC5sbSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUlVWc2VxLkRFU2VxMiIsICJTVkFzZXEuREVTZXEyIiwgIkNvbUJhdHNlcS5ERVNlcTIiKSkKYGBgCgoKIyMgUmVzdWx0cyAKCiMjIyBUUFIgdnMgRlBSIHsudGFic2V0fQoKYGBge3IsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQpmcHJfYWxsX2xzdCA8LSB0cHJfYWxsX2xzdCA8LSBsaXN0KCkKZm9yKGkgaW4gMTpsZW5ndGgoY29uZm91bmRpbmdfbGV2ZWxfdmVjKSl7CiAgZnByX2FsbF9sc3RbW2ldXSA8LSB0cHJfYWxsX2xzdFtbaV1dIDwtIGxpc3QoKQogIGZvcihqIGluIDE6bGVuZ3RoKGRpc3BfbGV2ZWxfdmVjKSl7CiAgICBleHBfbmFtZSA8LSBwYXN0ZTAoInNpbURDYmFzZV9OIiwgTl9zYW1wbGVzLCAiX2Rpc3BGQyIsIGRpc3BfbGV2ZWxfdmVjW2pdLAogICAgICAgICAgICAgICAgICAgICAgICJfcGVyY2VudCIsIGdzdWIoIi4iLCIiLCBjb25mb3VuZGluZ19sZXZlbF92ZWNbaV0sIGZpeGVkPVQpKQogICAgdHByX3JlcyA8LSByZWFkLmNzdihmaWxlLnBhdGgocmVzdWx0c19kaXIsIHNwcmludGYoJ3Rwcl8lcy5jc3YnLCBleHBfbmFtZSkpKQogICAgZnByX3JlcyA8LSByZWFkLmNzdihmaWxlLnBhdGgocmVzdWx0c19kaXIsIHNwcmludGYoJ2Zwcl8lcy5jc3YnLCBleHBfbmFtZSkpKQogICAgCiAgICB0cHJfcmVzJEJhc2VRdWFudC5lZGdlUiA8LSBOVUxMOyB0cHJfcmVzJEJhc2VRdWFudC5ERVNlcTIgPC0gTlVMTAogICAgZnByX3JlcyRCYXNlUXVhbnQuZWRnZVIgPC0gTlVMTDsgZnByX3JlcyRCYXNlUXVhbnQuREVTZXEyIDwtIE5VTEwKICAgIAogICAgdHByX2FsbF9sc3RbW2ldXVtbal1dIDwtIGFzLmxpc3QoY29sTWVhbnModHByX3JlcywgbmEucm09VFJVRSkpCiAgICBmcHJfYWxsX2xzdFtbaV1dW1tqXV0gIDwtIGFzLmxpc3QoY29sTWVhbnMoZnByX3JlcywgbmEucm09VFJVRSkpCiAgfQogIG5hbWVzKHRwcl9hbGxfbHN0W1tpXV0pIDwtIG5hbWVzKGZwcl9hbGxfbHN0W1tpXV0pIDwtIHBhc3RlMCgiRGlzcCIsIGRpc3BfbGV2ZWxfdmVjKQp9Cm5hbWVzKHRwcl9hbGxfbHN0KSA8LSBuYW1lcyhmcHJfYWxsX2xzdCkgPC0gcGFzdGUwKCJDbmZuZCIsIGNvbmZvdW5kaW5nX2xldmVsX3ZlYykKCiMjIEFsbCBtZXRob2RzCnRwcl9tZXJnZWQgPC0gbWVsdCh0cHJfYWxsX2xzdCk7IGNvbG5hbWVzKHRwcl9tZXJnZWQpIDwtIGMoIlRQUiIsICJNZXRob2QiLCAiRGlzcCIsICJDbmZuZCIpCmZwcl9tZXJnZWQgPC0gbWVsdChmcHJfYWxsX2xzdCk7IGNvbG5hbWVzKGZwcl9tZXJnZWQpIDwtIGMoIkZQUiIsICJNZXRob2QiLCAiRGlzcCIsICJDbmZuZCIpCnRwcl9tZXJnZWQkTWV0aG9kIDwtIGZhY3Rvcih0cHJfbWVyZ2VkJE1ldGhvZCwgbGV2ZWxzPWNvbG5hbWVzKHRwcl9yZXMpKQpmcHJfbWVyZ2VkJE1ldGhvZCA8LSBmYWN0b3IoZnByX21lcmdlZCRNZXRob2QsIGxldmVscz1jb2xuYW1lcyhmcHJfcmVzKSkKdHByX21lcmdlZCRDbmZuZCA8LSBmYWN0b3IodHByX21lcmdlZCRDbmZuZCwgbGV2ZWxzPXBhc3RlMCgiQ25mbmQiLCBjb25mb3VuZGluZ19sZXZlbF92ZWMpKQpmcHJfbWVyZ2VkJENuZm5kIDwtIGZhY3RvcihmcHJfbWVyZ2VkJENuZm5kLCBsZXZlbHM9cGFzdGUwKCJDbmZuZCIsIGNvbmZvdW5kaW5nX2xldmVsX3ZlYykpCgoKIyMgZWRnZVIgb25seQp0cHJfZWRnZVJfbHN0IDwtIGxhcHBseSh0cHJfYWxsX2xzdCwgZnVuY3Rpb24odDFfbHN0KXtsYXBwbHkodDFfbHN0LCBmdW5jdGlvbih0Ml9sc3Qpe3QyX2xzdFtzZWxfbWV0aG9kX2xpc3QkZWRnZVJdfSl9KQpmcHJfZWRnZVJfbHN0IDwtIGxhcHBseShmcHJfYWxsX2xzdCwgZnVuY3Rpb24oZjFfbHN0KXtsYXBwbHkoZjFfbHN0LCBmdW5jdGlvbihmMl9sc3Qpe2YyX2xzdFtzZWxfbWV0aG9kX2xpc3QkZWRnZVJdfSl9KQoKdHByX2VkZ2VSX21lcmdlZCA8LSBtZWx0KHRwcl9lZGdlUl9sc3QpOyBjb2xuYW1lcyh0cHJfZWRnZVJfbWVyZ2VkKSA8LSBjKCJUUFIiLCAiTWV0aG9kIiwgIkRpc3AiLCAiQ25mbmQiKQpmcHJfZWRnZVJfbWVyZ2VkIDwtIG1lbHQoZnByX2VkZ2VSX2xzdCk7IGNvbG5hbWVzKGZwcl9lZGdlUl9tZXJnZWQpIDwtIGMoIkZQUiIsICJNZXRob2QiLCAiRGlzcCIsICJDbmZuZCIpCnRwcl9lZGdlUl9tZXJnZWQkTWV0aG9kIDwtIGZhY3Rvcih0cHJfZWRnZVJfbWVyZ2VkJE1ldGhvZCwgbGV2ZWxzPXNlbF9tZXRob2RfbGlzdCRlZGdlUikKZnByX2VkZ2VSX21lcmdlZCRNZXRob2QgPC0gZmFjdG9yKGZwcl9lZGdlUl9tZXJnZWQkTWV0aG9kLCBsZXZlbHM9c2VsX21ldGhvZF9saXN0JGVkZ2VSKQp0cHJfZWRnZVJfbWVyZ2VkJENuZm5kIDwtIGZhY3Rvcih0cHJfZWRnZVJfbWVyZ2VkJENuZm5kLCBsZXZlbHM9cGFzdGUwKCJDbmZuZCIsIGNvbmZvdW5kaW5nX2xldmVsX3ZlYykpCmZwcl9lZGdlUl9tZXJnZWQkQ25mbmQgPC0gZmFjdG9yKGZwcl9lZGdlUl9tZXJnZWQkQ25mbmQsIGxldmVscz1wYXN0ZTAoIkNuZm5kIiwgY29uZm91bmRpbmdfbGV2ZWxfdmVjKSkKCgojIyBERVNlcTIgb25seQp0cHJfREVTZXEyX2xzdCA8LSBsYXBwbHkodHByX2FsbF9sc3QsIGZ1bmN0aW9uKHQxX2xzdCl7bGFwcGx5KHQxX2xzdCwgZnVuY3Rpb24odDJfbHN0KXt0Ml9sc3Rbc2VsX21ldGhvZF9saXN0JERFU2VxMl19KX0pCmZwcl9ERVNlcTJfbHN0IDwtIGxhcHBseShmcHJfYWxsX2xzdCwgZnVuY3Rpb24oZjFfbHN0KXtsYXBwbHkoZjFfbHN0LCBmdW5jdGlvbihmMl9sc3Qpe2YyX2xzdFtzZWxfbWV0aG9kX2xpc3QkREVTZXEyXX0pfSkKCnRwcl9ERVNlcTJfbWVyZ2VkIDwtIG1lbHQodHByX0RFU2VxMl9sc3QpOyBjb2xuYW1lcyh0cHJfREVTZXEyX21lcmdlZCkgPC0gYygiVFBSIiwgIk1ldGhvZCIsICJEaXNwIiwgIkNuZm5kIikKZnByX0RFU2VxMl9tZXJnZWQgPC0gbWVsdChmcHJfREVTZXEyX2xzdCk7IGNvbG5hbWVzKGZwcl9ERVNlcTJfbWVyZ2VkKSA8LSBjKCJGUFIiLCAiTWV0aG9kIiwgIkRpc3AiLCAiQ25mbmQiKQp0cHJfREVTZXEyX21lcmdlZCRNZXRob2QgPC0gZmFjdG9yKHRwcl9ERVNlcTJfbWVyZ2VkJE1ldGhvZCwgbGV2ZWxzPXNlbF9tZXRob2RfbGlzdCRERVNlcTIpCmZwcl9ERVNlcTJfbWVyZ2VkJE1ldGhvZCA8LSBmYWN0b3IoZnByX0RFU2VxMl9tZXJnZWQkTWV0aG9kLCBsZXZlbHM9c2VsX21ldGhvZF9saXN0JERFU2VxMikKdHByX0RFU2VxMl9tZXJnZWQkQ25mbmQgPC0gZmFjdG9yKHRwcl9ERVNlcTJfbWVyZ2VkJENuZm5kLCBsZXZlbHM9cGFzdGUwKCJDbmZuZCIsIGNvbmZvdW5kaW5nX2xldmVsX3ZlYykpCmZwcl9ERVNlcTJfbWVyZ2VkJENuZm5kIDwtIGZhY3RvcihmcHJfREVTZXEyX21lcmdlZCRDbmZuZCwgbGV2ZWxzPXBhc3RlMCgiQ25mbmQiLCBjb25mb3VuZGluZ19sZXZlbF92ZWMpKQpgYGAKCgojIyMjIExpbmUgcGxvdHMgey50YWJzZXR9CgojIyMjIyBGYWNldCBieSBjb25mb3VuZGluZyBsZXZlbHMKCmBgYHtyLCBlY2hvPUZBTFNFfQojIyBBbGwgbWV0aG9kcwpwX2ZwciA8LSBnZ3Bsb3QoZnByX21lcmdlZCwgYWVzKHg9RGlzcCwgeT1GUFIsIGdyb3VwPU1ldGhvZCwgY29sb3I9TWV0aG9kKSkgKwogIGZhY2V0X2dyaWQofkNuZm5kKSArCiAgZ2VvbV9saW5lKCkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0wLjA1LCBjb2w9InJlZCIsIGxpbmV0eXBlPSJkYXNoZWQiKSArCiAgbGFicyh0aXRsZT0iQWxsIikgKwogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT00NSwgaGp1c3Q9MSksIGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCkpIAogICN0aGVtZShheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCkpIApwX3RwciA8LSBnZ3Bsb3QodHByX21lcmdlZCwgYWVzKHg9RGlzcCwgeT1UUFIsIGdyb3VwPU1ldGhvZCwgY29sb3I9TWV0aG9kKSkgKwogIGZhY2V0X2dyaWQofkNuZm5kKSArCiAgZ2VvbV9saW5lKCkgKwogICNsYWJzKHRpdGxlPSJBbGwiKSArCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LCBoanVzdD0xKSwgYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSkgCnBfYWxsIDwtIGdnYXJyYW5nZShwbG90bGlzdD1saXN0KHBfZnByLCBwX3RwciksIG5yb3c9MiwgCiAgICAgICAgICAgICAgICAgICBjb21tb24ubGVnZW5kPVRSVUUsIGxlZ2VuZD0iYm90dG9tIikjLCBoZWlnaHRzPWMoNS41LDYpKQoKIyMgZWRnZVIgb25seQpwX2VkZ2VSX2ZwciA8LSBnZ3Bsb3QoZnByX2VkZ2VSX21lcmdlZCwgYWVzKHg9RGlzcCwgeT1GUFIsIGdyb3VwPU1ldGhvZCwgY29sb3I9TWV0aG9kKSkgKwogIGZhY2V0X2dyaWQofkNuZm5kKSArCiAgZ2VvbV9saW5lKCkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0wLjA1LCBjb2w9InJlZCIsIGxpbmV0eXBlPSJkYXNoZWQiKSArCiAgbGFicyh0aXRsZT0iZWRnZVIiKSArCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LCBoanVzdD0xKSwgYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSkgCiAgI3RoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSkgCnBfZWRnZVJfdHByIDwtIGdncGxvdCh0cHJfZWRnZVJfbWVyZ2VkLCBhZXMoeD1EaXNwLCB5PVRQUiwgZ3JvdXA9TWV0aG9kLCBjb2xvcj1NZXRob2QpKSArCiAgZmFjZXRfZ3JpZCh+Q25mbmQpICsKICBnZW9tX2xpbmUoKSArCiAgI2xhYnModGl0bGU9ImVkZ2VSIikgKwogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT00NSwgaGp1c3Q9MSksIGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCkpIApwX2VkZ2VSIDwtIGdnYXJyYW5nZShwbG90bGlzdD1saXN0KHBfZWRnZVJfZnByLCBwX2VkZ2VSX3RwciksIG5yb3c9MiwgCiAgICAgICAgICAgICAgICAgICAgIGNvbW1vbi5sZWdlbmQ9VFJVRSwgbGVnZW5kPSJib3R0b20iKSMsIGhlaWdodHM9Yyg1LjUsNikpCgojIyBERVNlcTIgb25seQpwX0RFU2VxMl9mcHIgPC0gZ2dwbG90KGZwcl9ERVNlcTJfbWVyZ2VkLCBhZXMoeD1EaXNwLCB5PUZQUiwgZ3JvdXA9TWV0aG9kLCBjb2xvcj1NZXRob2QpKSArCiAgZmFjZXRfZ3JpZCh+Q25mbmQpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTAuMDUsIGNvbD0icmVkIiwgbGluZXR5cGU9ImRhc2hlZCIpICsKICBsYWJzKHRpdGxlPSJERVNlcTIiKSArCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LCBoanVzdD0xKSwgYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSkgCiAgI3RoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfYmxhbmsoKSwgYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSkgCnBfREVTZXEyX3RwciA8LSBnZ3Bsb3QodHByX0RFU2VxMl9tZXJnZWQsIGFlcyh4PURpc3AsIHk9VFBSLCBncm91cD1NZXRob2QsIGNvbG9yPU1ldGhvZCkpICsKICBmYWNldF9ncmlkKH5DbmZuZCkgKwogIGdlb21fbGluZSgpICsKICAjbGFicyh0aXRsZT0iREVTZXEyIikgKwogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT00NSwgaGp1c3Q9MSksIGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCkpIApwX0RFU2VxMiA8LSBnZ2FycmFuZ2UocGxvdGxpc3Q9bGlzdChwX0RFU2VxMl9mcHIsIHBfREVTZXEyX3RwciksIG5yb3c9MiwgCiAgICAgICAgICAgICAgICAgICAgICBjb21tb24ubGVnZW5kPVRSVUUsIGxlZ2VuZD0iYm90dG9tIikjLCBoZWlnaHRzPWMoNS41LDYpKQoKI3AgPC0gZ2dhcnJhbmdlKHBsb3RsaXN0PWxpc3QocF9hbGwsIHBfZWRnZVIsIHBfREVTZXEyKSwgbnJvdz0zKQpwIDwtIGdnYXJyYW5nZShwbG90bGlzdD1saXN0KHBfZWRnZVIsIHBfREVTZXEyKSwgbnJvdz0yKQpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcud2lkdGg9NSwgZmlnLmhlaWdodD03fQpwCmBgYAoKCiMjIyMjIEZhY2V0IGJ5IGRpc3BlcnNpb24gbGV2ZWxzCgpgYGB7ciwgZWNobz1GQUxTRX0KIyMgQWxsIG1ldGhvZHMKcF9mcHIgPC0gZ2dwbG90KGZwcl9tZXJnZWQsIGFlcyh4PUNuZm5kLCB5PUZQUiwgZ3JvdXA9TWV0aG9kLCBjb2xvcj1NZXRob2QpKSArCiAgZmFjZXRfZ3JpZCh+RGlzcCkgKwogIGdlb21fbGluZSgpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MC4wNSwgY29sPSJyZWQiLCBsaW5ldHlwZT0iZGFzaGVkIikgKwogIGxhYnModGl0bGU9IkFsbCIpICsKICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9NDUsIGhqdXN0PTEpLCBheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpKSAKICAjdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF9ibGFuaygpLCBheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpKSAKcF90cHIgPC0gZ2dwbG90KHRwcl9tZXJnZWQsIGFlcyh4PUNuZm5kLCB5PVRQUiwgZ3JvdXA9TWV0aG9kLCBjb2xvcj1NZXRob2QpKSArCiAgZmFjZXRfZ3JpZCh+RGlzcCkgKwogIGdlb21fbGluZSgpICsKICAjbGFicyh0aXRsZT0iQWxsIikgKwogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT00NSwgaGp1c3Q9MSksIGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCkpIApwX2FsbCA8LSBnZ2FycmFuZ2UocGxvdGxpc3Q9bGlzdChwX2ZwciwgcF90cHIpLCBucm93PTIsIAogICAgICAgICAgICAgICAgICAgY29tbW9uLmxlZ2VuZD1UUlVFLCBsZWdlbmQ9ImJvdHRvbSIpIywgaGVpZ2h0cz1jKDUuNSw2KSkKCiMjIGVkZ2VSIG9ubHkKcF9lZGdlUl9mcHIgPC0gZ2dwbG90KGZwcl9lZGdlUl9tZXJnZWQsIGFlcyh4PUNuZm5kLCB5PUZQUiwgZ3JvdXA9TWV0aG9kLCBjb2xvcj1NZXRob2QpKSArCiAgZmFjZXRfZ3JpZCh+RGlzcCkgKwogIGdlb21fbGluZSgpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MC4wNSwgY29sPSJyZWQiLCBsaW5ldHlwZT0iZGFzaGVkIikgKwogIGxhYnModGl0bGU9ImVkZ2VSIikgKwogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT00NSwgaGp1c3Q9MSksIGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCkpIAogICN0aGVtZShheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCkpIApwX2VkZ2VSX3RwciA8LSBnZ3Bsb3QodHByX2VkZ2VSX21lcmdlZCwgYWVzKHg9Q25mbmQsIHk9VFBSLCBncm91cD1NZXRob2QsIGNvbG9yPU1ldGhvZCkpICsKICBmYWNldF9ncmlkKH5EaXNwKSArCiAgZ2VvbV9saW5lKCkgKwogICNsYWJzKHRpdGxlPSJlZGdlUiIpICsKICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9NDUsIGhqdXN0PTEpLCBheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpKSAKcF9lZGdlUiA8LSBnZ2FycmFuZ2UocGxvdGxpc3Q9bGlzdChwX2VkZ2VSX2ZwciwgcF9lZGdlUl90cHIpLCBucm93PTIsIAogICAgICAgICAgICAgICAgICAgICBjb21tb24ubGVnZW5kPVRSVUUsIGxlZ2VuZD0iYm90dG9tIikjLCBoZWlnaHRzPWMoNS41LDYpKQoKIyMgREVTZXEyIG9ubHkKcF9ERVNlcTJfZnByIDwtIGdncGxvdChmcHJfREVTZXEyX21lcmdlZCwgYWVzKHg9Q25mbmQsIHk9RlBSLCBncm91cD1NZXRob2QsIGNvbG9yPU1ldGhvZCkpICsKICBmYWNldF9ncmlkKH5EaXNwKSArCiAgZ2VvbV9saW5lKCkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0wLjA1LCBjb2w9InJlZCIsIGxpbmV0eXBlPSJkYXNoZWQiKSArCiAgbGFicyh0aXRsZT0iREVTZXEyIikgKwogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT00NSwgaGp1c3Q9MSksIGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCkpIAogICN0aGVtZShheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCkpIApwX0RFU2VxMl90cHIgPC0gZ2dwbG90KHRwcl9ERVNlcTJfbWVyZ2VkLCBhZXMoeD1DbmZuZCwgeT1UUFIsIGdyb3VwPU1ldGhvZCwgY29sb3I9TWV0aG9kKSkgKwogIGZhY2V0X2dyaWQofkRpc3ApICsKICBnZW9tX2xpbmUoKSArCiAgI2xhYnModGl0bGU9IkRFU2VxMiIpICsKICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9NDUsIGhqdXN0PTEpLCBheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpKSAKcF9ERVNlcTIgPC0gZ2dhcnJhbmdlKHBsb3RsaXN0PWxpc3QocF9ERVNlcTJfZnByLCBwX0RFU2VxMl90cHIpLCBucm93PTIsIAogICAgICAgICAgICAgICAgICAgICAgY29tbW9uLmxlZ2VuZD1UUlVFLCBsZWdlbmQ9ImJvdHRvbSIpIywgaGVpZ2h0cz1jKDUuNSw2KSkKCiNwIDwtIGdnYXJyYW5nZShwbG90bGlzdD1saXN0KHBfYWxsLCBwX2VkZ2VSLCBwX0RFU2VxMiksIG5yb3c9MykKcCA8LSBnZ2FycmFuZ2UocGxvdGxpc3Q9bGlzdChwX2VkZ2VSLCBwX0RFU2VxMiksIG5yb3c9MikKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLndpZHRoPTUuNSwgZmlnLmhlaWdodD03fQpwCmBgYAoKCiMjIyMgU2NhdHRlciBwbG90cwoKYGBge3IsIGVjaG89RkFMU0V9CmlmKGlkZW50aWNhbChmcHJfbWVyZ2VkWywtMV0sIHRwcl9tZXJnZWRbLC0xXSkpewogIHBlcmZzdGF0c19hbGwgPC0gZGF0YS5mcmFtZShUUFI9dHByX21lcmdlZCRUUFIsIEZQUj1mcHJfbWVyZ2VkJEZQUiwgdHByX21lcmdlZFssLTFdKQp9ZWxzZXtzdG9wKCJFUlJPUiBpbiBtZXJnaW5nIGRhdGEgZnJhbWVzISAtIEFsbCIpfQojaWRlbnRpY2FsKHBlcmZzdGF0c19hbGxbLC0xXSxmcHJfbWVyZ2VkKQoKaWYoaWRlbnRpY2FsKGZwcl9lZGdlUl9tZXJnZWRbLC0xXSwgdHByX2VkZ2VSX21lcmdlZFssLTFdKSl7CiAgcGVyZnN0YXRzX2VkZ2VSIDwtIGRhdGEuZnJhbWUoVFBSPXRwcl9lZGdlUl9tZXJnZWQkVFBSLCBGUFI9ZnByX2VkZ2VSX21lcmdlZCRGUFIsIHRwcl9lZGdlUl9tZXJnZWRbLC0xXSkKfWVsc2V7c3RvcCgiRVJST1IgaW4gbWVyZ2luZyBkYXRhIGZyYW1lcyEgLSBlZGdlUiIpfQojaWRlbnRpY2FsKHBlcmZzdGF0c19lZGdlUlssLTFdLCBmcHJfZWRnZVJfbWVyZ2VkKQoKaWYoaWRlbnRpY2FsKGZwcl9ERVNlcTJfbWVyZ2VkWywtMV0sIHRwcl9ERVNlcTJfbWVyZ2VkWywtMV0pKXsKICBwZXJmc3RhdHNfREVTZXEyIDwtIGRhdGEuZnJhbWUoVFBSPXRwcl9ERVNlcTJfbWVyZ2VkJFRQUiwgRlBSPWZwcl9ERVNlcTJfbWVyZ2VkJEZQUiwgdHByX0RFU2VxMl9tZXJnZWRbLC0xXSkKfWVsc2V7c3RvcCgiRVJST1IgaW4gbWVyZ2luZyBkYXRhIGZyYW1lcyEgLSBERVNlcTIiKX0KI2lkZW50aWNhbChwZXJmc3RhdHNfREVTZXEyWywtMV0sIGZwcl9ERVNlcTJfbWVyZ2VkKQoKYGBgCgpgYGB7ciwgZWNobz1GQUxTRX0KcDJfYWxsIDwtIGdncGxvdChwZXJmc3RhdHNfYWxsLCBhZXMoeD1GUFIsIHk9VFBSLCBncm91cD1NZXRob2QsIGNvbG9yPU1ldGhvZCwgc2hhcGU9TWV0aG9kKSkgKwogIGdlb21fcG9pbnQoc2l6ZT0zKSArCiAgZmFjZXRfZ3JpZChDbmZuZH5EaXNwKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz0xOm5sZXZlbHMocGVyZnN0YXRzX2FsbCRNZXRob2QpKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0PTAuMDUsIGxpbmV0eXBlPSJkYXNoZWQiKSArCiAgbGFicyh0aXRsZT0iQWxsIG1ldGhvZHMiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LCBoanVzdD0xKSkgCgpwMl9lZGdlUiA8LSBnZ3Bsb3QocGVyZnN0YXRzX2VkZ2VSLCBhZXMoeD1GUFIsIHk9VFBSLCBncm91cD1NZXRob2QsIGNvbG9yPU1ldGhvZCwgc2hhcGU9TWV0aG9kKSkgKwogIGdlb21fcG9pbnQoc2l6ZT0zKSArCiAgZmFjZXRfZ3JpZChDbmZuZH5EaXNwKSArCiAgc2NhbGVfc2hhcGVfbWFudWFsKHZhbHVlcz0xOm5sZXZlbHMocGVyZnN0YXRzX2VkZ2VSJE1ldGhvZCkpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9MC4wNSwgbGluZXR5cGU9ImRhc2hlZCIpICsKICBsYWJzKHRpdGxlPSJlZGdlUiIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9NDUsIGhqdXN0PTEpKSAKCnAyX0RFU2VxMiA8LSBnZ3Bsb3QocGVyZnN0YXRzX0RFU2VxMiwgYWVzKHg9RlBSLCB5PVRQUiwgZ3JvdXA9TWV0aG9kLCBjb2xvcj1NZXRob2QsIHNoYXBlPU1ldGhvZCkpICsKICBnZW9tX3BvaW50KHNpemU9MykgKwogIGZhY2V0X2dyaWQoQ25mbmR+RGlzcCkgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXM9MTpubGV2ZWxzKHBlcmZzdGF0c19ERVNlcTIkTWV0aG9kKSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdD0wLjA1LCBsaW5ldHlwZT0iZGFzaGVkIikgKwogIGxhYnModGl0bGU9IkRFU2VxMiIpICsKICB0aGVtZV9idygpICsKICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9NDUsIGhqdXN0PTEpKSAKICAKcDIgPC0gZ2dhcnJhbmdlKHAyX2VkZ2VSLCBwMl9ERVNlcTIsIG5yb3c9MikKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLndpZHRoPTUsIGZpZy5oZWlnaHQ9N30KcDIKYGBgCgoKCiMjIyBUUFIgKHNlbnNpdGl2aXR5KSB2cyBGRFIgKDEtcHJlY2lzaW9uKSB7LnRhYnNldH0KCmBgYHtyLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30Kcm0obGlzdD1scygpKQpyZXN1bHRzX2RpciA8LSAifi9Hb29nbGUgRHJpdmUvQ29tQmF0X3NlcS9ERV9kaXNwX2NvbmZvdW5kaW5nX2Jhc2UiCiNyZXN1bHRzX2RpciA8LSAifi95dXFpbmd6L0NvbUJhdF9zZXEvREVfZGlzcF9jb25mb3VuZGluZ19iYXNlIgpOX3NhbXBsZXMgPC0gMjAKCmRpc3BfbGV2ZWxfdmVjIDwtIDE6NQpjb25mb3VuZGluZ19sZXZlbF92ZWMgPC0gc2VxKGZyb209MC41LHRvPTAuMixieT0tMC4xKQpzZWxfbWV0aG9kX2xpc3QgPC0gbGlzdChlZGdlUj1jKCJCYXNlSW5kaS5lZGdlUiIsICMiQmFzZVF1YW50LmVkZ2VSIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkJhdGNoLmVkZ2VSIiwgIk9uZVN0ZXAuZWRnZVIiLCAiQ29tQmF0LmxtIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlJVVnNlcS5lZGdlUiIsICJTVkFzZXEuZWRnZVIiLCAiQ29tQmF0c2VxLmVkZ2VSIiksCiAgICAgICAgICAgICAgICAgICAgICAgIERFU2VxMj1jKCJCYXNlSW5kaS5ERVNlcTIiLCAjIkJhc2VRdWFudC5ERVNlcTIiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkJhdGNoLkRFU2VxMiIsICJPbmVTdGVwLkRFU2VxMiIsICJDb21CYXQubG0iLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlJVVnNlcS5ERVNlcTIiLCAiU1ZBc2VxLkRFU2VxMiIsICJDb21CYXRzZXEuREVTZXEyIikpCmBgYAoKYGBge3IsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQpmZHJfYWxsX2xzdCA8LSB0cHJfYWxsX2xzdCA8LSBsaXN0KCkKZm9yKGkgaW4gMTpsZW5ndGgoY29uZm91bmRpbmdfbGV2ZWxfdmVjKSl7CiAgZmRyX2FsbF9sc3RbW2ldXSA8LSB0cHJfYWxsX2xzdFtbaV1dIDwtIGxpc3QoKQogIGZvcihqIGluIDE6bGVuZ3RoKGRpc3BfbGV2ZWxfdmVjKSl7CiAgICBleHBfbmFtZSA8LSBwYXN0ZTAoInNpbURDYmFzZV9OIiwgTl9zYW1wbGVzLCAiX2Rpc3BGQyIsIGRpc3BfbGV2ZWxfdmVjW2pdLAogICAgICAgICAgICAgICAgICAgICAgICJfcGVyY2VudCIsIGdzdWIoIi4iLCIiLCBjb25mb3VuZGluZ19sZXZlbF92ZWNbaV0sIGZpeGVkPVQpKQogICAgdHByX3JlcyA8LSByZWFkLmNzdihmaWxlLnBhdGgocmVzdWx0c19kaXIsIHNwcmludGYoJ3RwckFESl8lcy5jc3YnLCBleHBfbmFtZSkpKQogICAgcHJlY19yZXMgPC0gcmVhZC5jc3YoZmlsZS5wYXRoKHJlc3VsdHNfZGlyLCBzcHJpbnRmKCdwcmVjQURKXyVzLmNzdicsIGV4cF9uYW1lKSkpCiAgICAKICAgIHRwcl9yZXMkQmFzZVF1YW50LmVkZ2VSIDwtIE5VTEw7IHRwcl9yZXMkQmFzZVF1YW50LkRFU2VxMiA8LSBOVUxMCiAgICBwcmVjX3JlcyRCYXNlUXVhbnQuZWRnZVIgPC0gTlVMTDsgcHJlY19yZXMkQmFzZVF1YW50LkRFU2VxMiA8LSBOVUxMCiAgICAKICAgIHRwcl9hbGxfbHN0W1tpXV1bW2pdXSA8LSBhcy5saXN0KGNvbE1lYW5zKHRwcl9yZXMsIG5hLnJtPVRSVUUpKQogICAgZmRyX2FsbF9sc3RbW2ldXVtbal1dICA8LSBhcy5saXN0KGNvbE1lYW5zKDEtcHJlY19yZXMsIG5hLnJtPVRSVUUpKQogIH0KICBuYW1lcyh0cHJfYWxsX2xzdFtbaV1dKSA8LSBuYW1lcyhmZHJfYWxsX2xzdFtbaV1dKSA8LSBwYXN0ZTAoIkRpc3AiLCBkaXNwX2xldmVsX3ZlYykKfQpuYW1lcyh0cHJfYWxsX2xzdCkgPC0gbmFtZXMoZmRyX2FsbF9sc3QpIDwtIHBhc3RlMCgiQ25mbmQiLCBjb25mb3VuZGluZ19sZXZlbF92ZWMpCgojIyBBbGwgbWV0aG9kcwp0cHJfbWVyZ2VkIDwtIG1lbHQodHByX2FsbF9sc3QpOyBjb2xuYW1lcyh0cHJfbWVyZ2VkKSA8LSBjKCJUUFIiLCAiTWV0aG9kIiwgIkRpc3AiLCAiQ25mbmQiKQpmZHJfbWVyZ2VkIDwtIG1lbHQoZmRyX2FsbF9sc3QpOyBjb2xuYW1lcyhmZHJfbWVyZ2VkKSA8LSBjKCJGRFIiLCAiTWV0aG9kIiwgIkRpc3AiLCAiQ25mbmQiKQp0cHJfbWVyZ2VkJE1ldGhvZCA8LSBmYWN0b3IodHByX21lcmdlZCRNZXRob2QsIGxldmVscz1jb2xuYW1lcyh0cHJfcmVzKSkKZmRyX21lcmdlZCRNZXRob2QgPC0gZmFjdG9yKGZkcl9tZXJnZWQkTWV0aG9kLCBsZXZlbHM9Y29sbmFtZXMocHJlY19yZXMpKQp0cHJfbWVyZ2VkJENuZm5kIDwtIGZhY3Rvcih0cHJfbWVyZ2VkJENuZm5kLCBsZXZlbHM9cGFzdGUwKCJDbmZuZCIsIGNvbmZvdW5kaW5nX2xldmVsX3ZlYykpCmZkcl9tZXJnZWQkQ25mbmQgPC0gZmFjdG9yKGZkcl9tZXJnZWQkQ25mbmQsIGxldmVscz1wYXN0ZTAoIkNuZm5kIiwgY29uZm91bmRpbmdfbGV2ZWxfdmVjKSkKCgojIyBlZGdlUiBvbmx5CnRwcl9lZGdlUl9sc3QgPC0gbGFwcGx5KHRwcl9hbGxfbHN0LCBmdW5jdGlvbih0MV9sc3Qpe2xhcHBseSh0MV9sc3QsIGZ1bmN0aW9uKHQyX2xzdCl7dDJfbHN0W3NlbF9tZXRob2RfbGlzdCRlZGdlUl19KX0pCmZkcl9lZGdlUl9sc3QgPC0gbGFwcGx5KGZkcl9hbGxfbHN0LCBmdW5jdGlvbihmMV9sc3Qpe2xhcHBseShmMV9sc3QsIGZ1bmN0aW9uKGYyX2xzdCl7ZjJfbHN0W3NlbF9tZXRob2RfbGlzdCRlZGdlUl19KX0pCgp0cHJfZWRnZVJfbWVyZ2VkIDwtIG1lbHQodHByX2VkZ2VSX2xzdCk7IGNvbG5hbWVzKHRwcl9lZGdlUl9tZXJnZWQpIDwtIGMoIlRQUiIsICJNZXRob2QiLCAiRGlzcCIsICJDbmZuZCIpCmZkcl9lZGdlUl9tZXJnZWQgPC0gbWVsdChmZHJfZWRnZVJfbHN0KTsgY29sbmFtZXMoZmRyX2VkZ2VSX21lcmdlZCkgPC0gYygiRkRSIiwgIk1ldGhvZCIsICJEaXNwIiwgIkNuZm5kIikKdHByX2VkZ2VSX21lcmdlZCRNZXRob2QgPC0gZmFjdG9yKHRwcl9lZGdlUl9tZXJnZWQkTWV0aG9kLCBsZXZlbHM9c2VsX21ldGhvZF9saXN0JGVkZ2VSKQpmZHJfZWRnZVJfbWVyZ2VkJE1ldGhvZCA8LSBmYWN0b3IoZmRyX2VkZ2VSX21lcmdlZCRNZXRob2QsIGxldmVscz1zZWxfbWV0aG9kX2xpc3QkZWRnZVIpCnRwcl9lZGdlUl9tZXJnZWQkQ25mbmQgPC0gZmFjdG9yKHRwcl9lZGdlUl9tZXJnZWQkQ25mbmQsIGxldmVscz1wYXN0ZTAoIkNuZm5kIiwgY29uZm91bmRpbmdfbGV2ZWxfdmVjKSkKZmRyX2VkZ2VSX21lcmdlZCRDbmZuZCA8LSBmYWN0b3IoZmRyX2VkZ2VSX21lcmdlZCRDbmZuZCwgbGV2ZWxzPXBhc3RlMCgiQ25mbmQiLCBjb25mb3VuZGluZ19sZXZlbF92ZWMpKQoKCiMjIERFU2VxMiBvbmx5CnRwcl9ERVNlcTJfbHN0IDwtIGxhcHBseSh0cHJfYWxsX2xzdCwgZnVuY3Rpb24odDFfbHN0KXtsYXBwbHkodDFfbHN0LCBmdW5jdGlvbih0Ml9sc3Qpe3QyX2xzdFtzZWxfbWV0aG9kX2xpc3QkREVTZXEyXX0pfSkKZmRyX0RFU2VxMl9sc3QgPC0gbGFwcGx5KGZkcl9hbGxfbHN0LCBmdW5jdGlvbihmMV9sc3Qpe2xhcHBseShmMV9sc3QsIGZ1bmN0aW9uKGYyX2xzdCl7ZjJfbHN0W3NlbF9tZXRob2RfbGlzdCRERVNlcTJdfSl9KQoKdHByX0RFU2VxMl9tZXJnZWQgPC0gbWVsdCh0cHJfREVTZXEyX2xzdCk7IGNvbG5hbWVzKHRwcl9ERVNlcTJfbWVyZ2VkKSA8LSBjKCJUUFIiLCAiTWV0aG9kIiwgIkRpc3AiLCAiQ25mbmQiKQpmZHJfREVTZXEyX21lcmdlZCA8LSBtZWx0KGZkcl9ERVNlcTJfbHN0KTsgY29sbmFtZXMoZmRyX0RFU2VxMl9tZXJnZWQpIDwtIGMoIkZEUiIsICJNZXRob2QiLCAiRGlzcCIsICJDbmZuZCIpCnRwcl9ERVNlcTJfbWVyZ2VkJE1ldGhvZCA8LSBmYWN0b3IodHByX0RFU2VxMl9tZXJnZWQkTWV0aG9kLCBsZXZlbHM9c2VsX21ldGhvZF9saXN0JERFU2VxMikKZmRyX0RFU2VxMl9tZXJnZWQkTWV0aG9kIDwtIGZhY3RvcihmZHJfREVTZXEyX21lcmdlZCRNZXRob2QsIGxldmVscz1zZWxfbWV0aG9kX2xpc3QkREVTZXEyKQp0cHJfREVTZXEyX21lcmdlZCRDbmZuZCA8LSBmYWN0b3IodHByX0RFU2VxMl9tZXJnZWQkQ25mbmQsIGxldmVscz1wYXN0ZTAoIkNuZm5kIiwgY29uZm91bmRpbmdfbGV2ZWxfdmVjKSkKZmRyX0RFU2VxMl9tZXJnZWQkQ25mbmQgPC0gZmFjdG9yKGZkcl9ERVNlcTJfbWVyZ2VkJENuZm5kLCBsZXZlbHM9cGFzdGUwKCJDbmZuZCIsIGNvbmZvdW5kaW5nX2xldmVsX3ZlYykpCmBgYAoKCiMjIyMgTGluZSBwbG90cyB7LnRhYnNldH0KCiMjIyMjIEZhY2V0IGJ5IGNvbmZvdW5kaW5nIGxldmVscwoKYGBge3IsIGVjaG89RkFMU0UsIHJlc3VsdHM9ImhpZGUifQojIyBBbGwgbWV0aG9kcwpwX2ZkciA8LSBnZ3Bsb3QoZmRyX21lcmdlZCwgYWVzKHg9RGlzcCwgeT1GRFIsIGdyb3VwPU1ldGhvZCwgY29sb3I9TWV0aG9kKSkgKwogIGZhY2V0X2dyaWQofkNuZm5kKSArCiAgZ2VvbV9saW5lKCkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0wLjA1LCBjb2w9InJlZCIsIGxpbmV0eXBlPSJkYXNoZWQiKSArCiAgbGFicyh0aXRsZT0iQWxsIiwgeT0iMSAtIFByZWNpc2lvbiAoRkRSKSIpICsKICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9NDUsIGhqdXN0PTEpLCBheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpKSAKcF90cHIgPC0gZ2dwbG90KHRwcl9tZXJnZWQsIGFlcyh4PURpc3AsIHk9VFBSLCBncm91cD1NZXRob2QsIGNvbG9yPU1ldGhvZCkpICsKICBmYWNldF9ncmlkKH5DbmZuZCkgKwogIGdlb21fbGluZSgpICsKICBsYWJzKHk9IlNlbnNpdGl2aXR5IChUUFIpIikgKwogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT00NSwgaGp1c3Q9MSksIGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCkpIApwX2FsbCA8LSBnZ2FycmFuZ2UocGxvdGxpc3Q9bGlzdChwX2ZkciwgcF90cHIpLCBucm93PTIsIAogICAgICAgICAgICAgICAgICAgY29tbW9uLmxlZ2VuZD1UUlVFLCBsZWdlbmQ9ImJvdHRvbSIpCgojIyBlZGdlUiBvbmx5CnBfZWRnZVJfZmRyIDwtIGdncGxvdChmZHJfZWRnZVJfbWVyZ2VkLCBhZXMoeD1EaXNwLCB5PUZEUiwgZ3JvdXA9TWV0aG9kLCBjb2xvcj1NZXRob2QpKSArCiAgZmFjZXRfZ3JpZCh+Q25mbmQpICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTAuMDUsIGNvbD0icmVkIiwgbGluZXR5cGU9ImRhc2hlZCIpICsKICBsYWJzKHRpdGxlPSJlZGdlUiIsIHk9IjEgLSBQcmVjaXNpb24gKEZEUikiKSArCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LCBoanVzdD0xKSwgYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSkgCnBfZWRnZVJfdHByIDwtIGdncGxvdCh0cHJfZWRnZVJfbWVyZ2VkLCBhZXMoeD1EaXNwLCB5PVRQUiwgZ3JvdXA9TWV0aG9kLCBjb2xvcj1NZXRob2QpKSArCiAgZmFjZXRfZ3JpZCh+Q25mbmQpICsKICBnZW9tX2xpbmUoKSArCiAgbGFicyh5PSJTZW5zaXRpdml0eSAoVFBSKSIpICsKICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9NDUsIGhqdXN0PTEpLCBheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpKSAKcF9lZGdlUiA8LSBnZ2FycmFuZ2UocGxvdGxpc3Q9bGlzdChwX2VkZ2VSX2ZkciwgcF9lZGdlUl90cHIpLCBucm93PTIsIAogICAgICAgICAgICAgICAgICAgICBjb21tb24ubGVnZW5kPVRSVUUsIGxlZ2VuZD0iYm90dG9tIikKCiMjIERFU2VxMiBvbmx5CnBfREVTZXEyX2ZkciA8LSBnZ3Bsb3QoZmRyX0RFU2VxMl9tZXJnZWQsIGFlcyh4PURpc3AsIHk9RkRSLCBncm91cD1NZXRob2QsIGNvbG9yPU1ldGhvZCkpICsKICBmYWNldF9ncmlkKH5DbmZuZCkgKwogIGdlb21fbGluZSgpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MC4wNSwgY29sPSJyZWQiLCBsaW5ldHlwZT0iZGFzaGVkIikgKwogIGxhYnModGl0bGU9IkRFU2VxMiIsIHk9IjEgLSBQcmVjaXNpb24gKEZEUikiKSArCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LCBoanVzdD0xKSwgYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSkgCnBfREVTZXEyX3RwciA8LSBnZ3Bsb3QodHByX0RFU2VxMl9tZXJnZWQsIGFlcyh4PURpc3AsIHk9VFBSLCBncm91cD1NZXRob2QsIGNvbG9yPU1ldGhvZCkpICsKICBmYWNldF9ncmlkKH5DbmZuZCkgKwogIGdlb21fbGluZSgpICsKICBsYWJzKHk9IlNlbnNpdGl2aXR5IChUUFIpIikgKwogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT00NSwgaGp1c3Q9MSksIGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCkpIApwX0RFU2VxMiA8LSBnZ2FycmFuZ2UocGxvdGxpc3Q9bGlzdChwX0RFU2VxMl9mZHIsIHBfREVTZXEyX3RwciksIG5yb3c9MiwgCiAgICAgICAgICAgICAgICAgICAgICBjb21tb24ubGVnZW5kPVRSVUUsIGxlZ2VuZD0iYm90dG9tIikKCnAgPC0gZ2dhcnJhbmdlKHBsb3RsaXN0PWxpc3QocF9lZGdlUiwgcF9ERVNlcTIpLCBucm93PTIpCmBgYAoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy53aWR0aD01LCBmaWcuaGVpZ2h0PTd9CnAKYGBgCgoKIyMjIyMgRmFjZXQgYnkgZGlzcGVyc2lvbiBsZXZlbHMKCmBgYHtyLCBlY2hvPUZBTFNFfQojIyBBbGwgbWV0aG9kcwpwX2ZkciA8LSBnZ3Bsb3QoZmRyX21lcmdlZCwgYWVzKHg9Q25mbmQsIHk9RkRSLCBncm91cD1NZXRob2QsIGNvbG9yPU1ldGhvZCkpICsKICBmYWNldF9ncmlkKH5EaXNwKSArCiAgZ2VvbV9saW5lKCkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdD0wLjA1LCBjb2w9InJlZCIsIGxpbmV0eXBlPSJkYXNoZWQiKSArCiAgbGFicyh0aXRsZT0iQWxsIiwgeT0iMSAtIFByZWNpc2lvbiAoRkRSKSIpICsKICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9NDUsIGhqdXN0PTEpLCBheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpKSAKcF90cHIgPC0gZ2dwbG90KHRwcl9tZXJnZWQsIGFlcyh4PUNuZm5kLCB5PVRQUiwgZ3JvdXA9TWV0aG9kLCBjb2xvcj1NZXRob2QpKSArCiAgZmFjZXRfZ3JpZCh+RGlzcCkgKwogIGdlb21fbGluZSgpICsKICBsYWJzKHk9IlNlbnNpdGl2aXR5IChUUFIpIikgKwogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT00NSwgaGp1c3Q9MSksIGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCkpIApwX2FsbCA8LSBnZ2FycmFuZ2UocGxvdGxpc3Q9bGlzdChwX2ZkciwgcF90cHIpLCBucm93PTIsIAogICAgICAgICAgICAgICAgICAgY29tbW9uLmxlZ2VuZD1UUlVFLCBsZWdlbmQ9ImJvdHRvbSIpCgojIyBlZGdlUiBvbmx5CnBfZWRnZVJfZmRyIDwtIGdncGxvdChmZHJfZWRnZVJfbWVyZ2VkLCBhZXMoeD1DbmZuZCwgeT1GRFIsIGdyb3VwPU1ldGhvZCwgY29sb3I9TWV0aG9kKSkgKwogIGZhY2V0X2dyaWQofkRpc3ApICsKICBnZW9tX2xpbmUoKSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0PTAuMDUsIGNvbD0icmVkIiwgbGluZXR5cGU9ImRhc2hlZCIpICsKICBsYWJzKHRpdGxlPSJlZGdlUiIsIHk9IjEgLSBQcmVjaXNpb24gKEZEUikiKSArCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LCBoanVzdD0xKSwgYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSkgCnBfZWRnZVJfdHByIDwtIGdncGxvdCh0cHJfZWRnZVJfbWVyZ2VkLCBhZXMoeD1DbmZuZCwgeT1UUFIsIGdyb3VwPU1ldGhvZCwgY29sb3I9TWV0aG9kKSkgKwogIGZhY2V0X2dyaWQofkRpc3ApICsKICBnZW9tX2xpbmUoKSArCiAgbGFicyh5PSJTZW5zaXRpdml0eSAoVFBSKSIpICsKICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9NDUsIGhqdXN0PTEpLCBheGlzLnRpdGxlLng9ZWxlbWVudF9ibGFuaygpKSAKcF9lZGdlUiA8LSBnZ2FycmFuZ2UocGxvdGxpc3Q9bGlzdChwX2VkZ2VSX2ZkciwgcF9lZGdlUl90cHIpLCBucm93PTIsIAogICAgICAgICAgICAgICAgICAgICBjb21tb24ubGVnZW5kPVRSVUUsIGxlZ2VuZD0iYm90dG9tIikKCiMjIERFU2VxMiBvbmx5CnBfREVTZXEyX2ZkciA8LSBnZ3Bsb3QoZmRyX0RFU2VxMl9tZXJnZWQsIGFlcyh4PUNuZm5kLCB5PUZEUiwgZ3JvdXA9TWV0aG9kLCBjb2xvcj1NZXRob2QpKSArCiAgZmFjZXRfZ3JpZCh+RGlzcCkgKwogIGdlb21fbGluZSgpICsKICBnZW9tX2hsaW5lKHlpbnRlcmNlcHQ9MC4wNSwgY29sPSJyZWQiLCBsaW5ldHlwZT0iZGFzaGVkIikgKwogIGxhYnModGl0bGU9IkRFU2VxMiIsIHk9IjEgLSBQcmVjaXNpb24gKEZEUikiKSArCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LCBoanVzdD0xKSwgYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSkgCnBfREVTZXEyX3RwciA8LSBnZ3Bsb3QodHByX0RFU2VxMl9tZXJnZWQsIGFlcyh4PUNuZm5kLCB5PVRQUiwgZ3JvdXA9TWV0aG9kLCBjb2xvcj1NZXRob2QpKSArCiAgZmFjZXRfZ3JpZCh+RGlzcCkgKwogIGdlb21fbGluZSgpICsKICBsYWJzKHk9IlNlbnNpdGl2aXR5IChUUFIpIikgKwogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT00NSwgaGp1c3Q9MSksIGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCkpIApwX0RFU2VxMiA8LSBnZ2FycmFuZ2UocGxvdGxpc3Q9bGlzdChwX0RFU2VxMl9mZHIsIHBfREVTZXEyX3RwciksIG5yb3c9MiwgCiAgICAgICAgICAgICAgICAgICAgICBjb21tb24ubGVnZW5kPVRSVUUsIGxlZ2VuZD0iYm90dG9tIikKCnAgPC0gZ2dhcnJhbmdlKHBsb3RsaXN0PWxpc3QocF9lZGdlUiwgcF9ERVNlcTIpLCBucm93PTIpCmBgYAoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy53aWR0aD01LjUsIGZpZy5oZWlnaHQ9N30KcApgYGAKCgojIyMjIFNjYXR0ZXIgcGxvdHMKClNpbWlsYXIgcGxvdCAoc2Vuc2l0aXZpdHkgdnMgMS1GRFIpIGFzIEZpZ3VyZSA2IGluIERFU2VxMiBwYXBlci4KCmBgYHtyLCBlY2hvPUZBTFNFfQppZihpZGVudGljYWwoZmRyX21lcmdlZFssLTFdLCB0cHJfbWVyZ2VkWywtMV0pKXsKICBwZXJmc3RhdHNfYWxsIDwtIGRhdGEuZnJhbWUoVFBSPXRwcl9tZXJnZWQkVFBSLCBGRFI9ZmRyX21lcmdlZCRGRFIsIHRwcl9tZXJnZWRbLC0xXSkKfWVsc2V7c3RvcCgiRVJST1IgaW4gbWVyZ2luZyBkYXRhIGZyYW1lcyEgLSBBbGwiKX0KI2lkZW50aWNhbChwZXJmc3RhdHNfYWxsWywtMV0sZmRyX21lcmdlZCkKCmlmKGlkZW50aWNhbChmZHJfZWRnZVJfbWVyZ2VkWywtMV0sIHRwcl9lZGdlUl9tZXJnZWRbLC0xXSkpewogIHBlcmZzdGF0c19lZGdlUiA8LSBkYXRhLmZyYW1lKFRQUj10cHJfZWRnZVJfbWVyZ2VkJFRQUiwgRkRSPWZkcl9lZGdlUl9tZXJnZWQkRkRSLCB0cHJfZWRnZVJfbWVyZ2VkWywtMV0pCn1lbHNle3N0b3AoIkVSUk9SIGluIG1lcmdpbmcgZGF0YSBmcmFtZXMhIC0gZWRnZVIiKX0KI2lkZW50aWNhbChwZXJmc3RhdHNfZWRnZVJbLC0xXSwgZmRyX2VkZ2VSX21lcmdlZCkKCmlmKGlkZW50aWNhbChmZHJfREVTZXEyX21lcmdlZFssLTFdLCB0cHJfREVTZXEyX21lcmdlZFssLTFdKSl7CiAgcGVyZnN0YXRzX0RFU2VxMiA8LSBkYXRhLmZyYW1lKFRQUj10cHJfREVTZXEyX21lcmdlZCRUUFIsIEZEUj1mZHJfREVTZXEyX21lcmdlZCRGRFIsIHRwcl9ERVNlcTJfbWVyZ2VkWywtMV0pCn1lbHNle3N0b3AoIkVSUk9SIGluIG1lcmdpbmcgZGF0YSBmcmFtZXMhIC0gREVTZXEyIil9CiNpZGVudGljYWwocGVyZnN0YXRzX0RFU2VxMlssLTFdLCBmZHJfREVTZXEyX21lcmdlZCkKCmBgYAoKYGBge3IsIGVjaG89RkFMU0V9CnAyX2FsbCA8LSBnZ3Bsb3QocGVyZnN0YXRzX2FsbCwgYWVzKHg9RkRSLCB5PVRQUiwgZ3JvdXA9TWV0aG9kLCBjb2xvcj1NZXRob2QsIHNoYXBlPU1ldGhvZCkpICsKICBnZW9tX3BvaW50KHNpemU9MykgKwogIGZhY2V0X2dyaWQoQ25mbmR+RGlzcCkgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXM9MTpubGV2ZWxzKHBlcmZzdGF0c19hbGwkTWV0aG9kKSkgKwogIGdlb21fdmxpbmUoeGludGVyY2VwdD0wLjA1LCBsaW5ldHlwZT0iZGFzaGVkIikgKwogIGxhYnModGl0bGU9IkFsbCBtZXRob2RzIiwgeD0iMSAtIFByZWNpc2lvbiAoRkRSKSIsIHk9IlNlbnNpdGl2aXR5IChUUFIpIikgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT00NSwgaGp1c3Q9MSkpIAoKcDJfZWRnZVIgPC0gZ2dwbG90KHBlcmZzdGF0c19lZGdlUiwgYWVzKHg9RkRSLCB5PVRQUiwgZ3JvdXA9TWV0aG9kLCBjb2xvcj1NZXRob2QsIHNoYXBlPU1ldGhvZCkpICsKICBnZW9tX3BvaW50KHNpemU9MykgKwogIGZhY2V0X2dyaWQoQ25mbmR+RGlzcCkgKwogIHNjYWxlX3NoYXBlX21hbnVhbCh2YWx1ZXM9MTpubGV2ZWxzKHBlcmZzdGF0c19lZGdlUiRNZXRob2QpKSArCiAgZ2VvbV92bGluZSh4aW50ZXJjZXB0PTAuMDUsIGxpbmV0eXBlPSJkYXNoZWQiKSArCiAgbGFicyh0aXRsZT0iZWRnZVIiLCB4PSIxIC0gUHJlY2lzaW9uIChGRFIpIiwgeT0iU2Vuc2l0aXZpdHkgKFRQUikiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LCBoanVzdD0xKSkgCgpwMl9ERVNlcTIgPC0gZ2dwbG90KHBlcmZzdGF0c19ERVNlcTIsIGFlcyh4PUZEUiwgeT1UUFIsIGdyb3VwPU1ldGhvZCwgY29sb3I9TWV0aG9kLCBzaGFwZT1NZXRob2QpKSArCiAgZ2VvbV9wb2ludChzaXplPTMpICsKICBmYWNldF9ncmlkKENuZm5kfkRpc3ApICsKICBzY2FsZV9zaGFwZV9tYW51YWwodmFsdWVzPTE6bmxldmVscyhwZXJmc3RhdHNfREVTZXEyJE1ldGhvZCkpICsKICBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9MC4wNSwgbGluZXR5cGU9ImRhc2hlZCIpICsKICBsYWJzKHRpdGxlPSJERVNlcTIiLCB4PSIxIC0gUHJlY2lzaW9uIChGRFIpIiwgeT0iU2Vuc2l0aXZpdHkgKFRQUikiKSArCiAgdGhlbWVfYncoKSArCiAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTQ1LCBoanVzdD0xKSkgCiAgCnAyIDwtIGdnYXJyYW5nZShwMl9lZGdlUiwgcDJfREVTZXEyLCBucm93PTIpCmBgYAoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy53aWR0aD01LCBmaWcuaGVpZ2h0PTd9CnAyCmBgYAoKCgojIyBUaG91Z2h0cyAmIGZ1dHVyZSB3b3JrCgoqIAo=